#!/bin/sh
# expects 32-bit hex value integer, such as 01234ABC, outputs IEEE floating point bitwise representation of an integer 
# based upon https://locklessinc.com/articles/i2f/

FILD_FRAC_BITS=23
FILD_MASK=$(((1 << $FILD_FRAC_BITS) - 1))
INPUT_VAL=

if [ $# -ge 1 ]; then
	INPUT_VAL=$1
else
	read INPUT_VAL
fi

HexToBitStr() {
	local BYTE_STRING=$1
	local OCTET=
	while [ -n "$BYTE_STRING" ]; do
		OCTET=${BYTE_STRING:0:2}
		echo $((0x$OCTET)) | awk '{r="";a=$1;while(a){r=a%2r;a=int(a/2)}printf"%08d",r}' 
		BYTE_STRING=${BYTE_STRING:2}
	done
}

BitStrToHex() {
	local BIT_STR=$1
	local OCTET=
	# for BusyBox with awk w/o math support
	if uname -m | grep -q armv7; then
		while [ -n "$BIT_STR" ]; do
			OCTET=${BIT_STR:0:8}
			echo $OCTET | awk '{o="";v="";r="";a=$1;for(i=1;i<=length(a);i++){r=substr(a,i,1);v=system("return $((2**"r*(length(a)-i)"))");o=o+r*v;}printf"%02x",o}' 
			BIT_STR=${BIT_STR:8}
		done
	else
		echo $BIT_STR | awk '{o="";v="";r="";a=$1;for(i=1; i<=length(a); i++){r=substr(a,i,1); v=2**(r*(length(a)-i)); o=o+r*v; } printf"%08x",o; }'
	fi
}

CircShiftR() {
	local IN_STR=$1
	local STR_LEN=${#IN_STR}
	local COUNT=$(($2 % $STR_LEN))
	local REST=$(($STR_LEN - $COUNT))
	echo "${IN_STR:$REST}${IN_STR:0:$REST}"
}

GetMSB() {
	local IN_STR=$1
	local REST=${IN_STR#*1}
	echo $((32 - (${#IN_STR} - ${#REST})))
}


if [ $((0x${INPUT_VAL})) -eq 0 ]; then
	echo -n 00000000
	exit
fi

BIT_STRING=
MSB=
ROTC=
ROT_BITS=
FRAC=
EXP=
OUTPUT=

if [ $((0x${INPUT_VAL} & 0x80000000)) -eq 0 ]; then
	BIT_STRING=$(HexToBitStr $INPUT_VAL)
else
	INPUT_NEG=$(printf "%08x" $(((-0x${INPUT_VAL}) & 0x7fffffff)))
	BIT_STRING=$(HexToBitStr $INPUT_NEG)
fi

MSB=$(GetMSB $BIT_STRING)
ROTC=$((($MSB - $FILD_FRAC_BITS) & 31))
ROT_BITS=$(CircShiftR $BIT_STRING $ROTC)
FRAC=$((0x$(BitStrToHex $ROT_BITS) & $FILD_MASK))
EXP=$(((127 + $MSB) << $FILD_FRAC_BITS))
OUTPUT=$(($FRAC + $EXP))

if [ $((0x${INPUT_VAL} & 0x80000000)) -eq 0 ]; then
	printf "%08x" $OUTPUT
else
	OUTPUT_NEG=$(printf "%08x\n" $(($OUTPUT | 0x80000000)))
	echo -n ${OUTPUT_NEG:$((${#OUTPUT_NEG}-8))}
fi

# $ perl -e 'printf "%08x", (-92347987 & 0xffffffff)' | bash fild.sh | { read ins; echo -n -e "\x${ins:6:2}\x${ins:4:2}\x${ins:2:2}\x${ins:0:2}"; } | od -f | head -n1 | awk '{print $2}'
# ostr=$(printf "%08x" 10); echo -n ${ostr:$((${#ostr}-8))} | ./fild.sh | { read ins; echo -n -e "\x${ins:6:2}\x${ins:4:2}\x${ins:2:2}\x${ins:0:2}"; } | od -t f4 | head -n1 | awk '{print $2}'
